using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace UnityEngine.Recorder
{
	[Serializable]
	public class InputSettingsList : IEnumerable<RecorderInputSetting>, IEnumerable
	{
		[SerializeField]
		private List<RecorderInputSetting> m_InputsSettingsAssets;

		private List<RecorderInputSetting> m_InputsSettings;

		public string ownerRecorderSettingsAssetId;

		public bool hasBrokenBindings
		{
			get
			{
				foreach (RecorderInputSetting item in m_InputsSettings.ToList())
				{
					if (item == null || item is InputBinder)
					{
						return true;
					}
				}
				return false;
			}
		}

		public RecorderInputSetting this[int index]
		{
			get
			{
				return m_InputsSettings[index];
			}
			set
			{
				ReplaceAt(index, value);
			}
		}

		public int Count => m_InputsSettings.Count;

		public void OnEnable(string ownerSettingsAssetId)
		{
			ownerRecorderSettingsAssetId = ownerSettingsAssetId;
			Reset();
		}

		public void Reset()
		{
			if (m_InputsSettingsAssets == null)
			{
				m_InputsSettingsAssets = new List<RecorderInputSetting>();
			}
			Rebuild();
		}

		public void Rebuild()
		{
			m_InputsSettings = new List<RecorderInputSetting>();
			foreach (RecorderInputSetting inputsSettingsAsset in m_InputsSettingsAssets)
			{
				if (inputsSettingsAsset is InputBinder)
				{
					InputSettingsComponent inputsComponent = SceneHook.GetInputsComponent(ownerRecorderSettingsAssetId);
					bool flag = false;
					foreach (RecorderInputSetting setting in inputsComponent.m_Settings)
					{
						if (setting.m_Id == inputsSettingsAsset.m_Id)
						{
							m_InputsSettings.Add(setting);
							flag = true;
							break;
						}
					}
					if (!flag)
					{
						InputBinder inputBinder = inputsSettingsAsset as InputBinder;
						if (string.IsNullOrEmpty(inputBinder.typeName))
						{
							UnityEngine.Debug.LogError("Recorder Input asset in invalid!");
						}
						else
						{
							if (Application.isPlaying)
							{
								UnityEngine.Debug.LogError("Recorder input setting missing from scene, adding with default state.");
							}
							else if (Verbose.enabled)
							{
								UnityEngine.Debug.Log("Recorder input setting missing from scene, adding with default state.");
							}
							RecorderInputSetting recorderInputSetting = ScriptableObject.CreateInstance(inputBinder.inputType) as RecorderInputSetting;
							recorderInputSetting.m_Id = inputsSettingsAsset.m_Id;
							m_InputsSettings.Add(recorderInputSetting);
						}
					}
				}
				else
				{
					m_InputsSettings.Add(inputsSettingsAsset);
				}
			}
		}

		public bool ValidityCheck(List<string> errors)
		{
			foreach (RecorderInputSetting inputsSetting in m_InputsSettings)
			{
				if (!inputsSetting.ValidityCheck(errors))
				{
					return false;
				}
			}
			return true;
		}

		public IEnumerator<RecorderInputSetting> GetEnumerator()
		{
			return ((IEnumerable<RecorderInputSetting>)m_InputsSettings).GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		public void AddRange(List<RecorderInputSetting> list)
		{
			foreach (RecorderInputSetting item in list)
			{
				Add(item);
			}
		}

		public void Add(RecorderInputSetting input)
		{
			m_InputsSettings.Add(null);
			m_InputsSettingsAssets.Add(null);
			ReplaceAt(m_InputsSettings.Count - 1, input);
		}

		public void Rebind(RecorderInputSetting input)
		{
			if (input is InputBinder)
			{
				UnityEngine.Debug.LogError("Cannot bind a InputBinder object!");
				return;
			}
			int num = 0;
			while (true)
			{
				if (num < m_InputsSettings.Count)
				{
					RecorderInputSetting recorderInputSetting = m_InputsSettings[num];
					InputBinder inputBinder = recorderInputSetting as InputBinder;
					if (inputBinder != null && inputBinder.m_Id == input.m_Id)
					{
						break;
					}
					num++;
					continue;
				}
				return;
			}
			m_InputsSettings[num] = input;
		}

		public void Remove(RecorderInputSetting input)
		{
			for (int i = 0; i < m_InputsSettings.Count; i++)
			{
				if (m_InputsSettings[i] == input)
				{
					ReleaseAt(i);
					m_InputsSettings.RemoveAt(i);
					m_InputsSettingsAssets.RemoveAt(i);
				}
			}
		}

		public void ReplaceAt(int index, RecorderInputSetting input)
		{
			if (m_InputsSettingsAssets == null || m_InputsSettings.Count <= index)
			{
				throw new ArgumentException("Index out of range");
			}
			ReleaseAt(index);
			m_InputsSettings[index] = input;
			if (input.storeInScene)
			{
				InputBinder inputBinder = ScriptableObject.CreateInstance<InputBinder>();
				inputBinder.name = "Scene-Stored";
				inputBinder.m_DisplayName = input.m_DisplayName;
				inputBinder.typeName = input.GetType().AssemblyQualifiedName;
				inputBinder.m_Id = input.m_Id;
				m_InputsSettingsAssets[index] = inputBinder;
				SceneHook.RegisterInputSettingObj(ownerRecorderSettingsAssetId, input);
			}
			else
			{
				m_InputsSettingsAssets[index] = input;
			}
		}

		private void ReleaseAt(int index)
		{
			UnityHelpers.Destroy(m_InputsSettingsAssets[index], allowDestroyingAssets: true);
			m_InputsSettings[index] = null;
			m_InputsSettingsAssets[index] = null;
		}

		public void OnDestroy()
		{
			for (int i = 0; i < m_InputsSettingsAssets.Count; i++)
			{
				if (m_InputsSettingsAssets[i] is InputBinder)
				{
					SceneHook.UnregisterInputSettingObj(ownerRecorderSettingsAssetId, m_InputsSettings[i]);
				}
				UnityHelpers.Destroy(m_InputsSettingsAssets[i], allowDestroyingAssets: true);
			}
		}
	}
}
